package dao

import (
	"context"
	"errors"
	"ldaccount/pkg/db/pgex"
	"ldaccount/pkg/rpc"
	"strings"

	"github.com/google/uuid"

	open_pb "ldaccount/api/pb/client/open/api/open/v1"
	"ldaccount/internal/model"
	"ldaccount/internal/object"
	"ldaccount/pkg/util"
)

type LoginChannelRepo interface {
	// CreateLoginChannel 新增渠道
	CreateLoginChannel(ctx context.Context, channel *model.LoginChannel) (int64, error)
	// GetLoginChannelByOpenId 根据 openid 查询渠道
	GetLoginChannelByOpenId(ctx context.Context, appId, openId string, platform int8) (*model.LoginChannel, error)
	// GetMpLoginQrcode 获取登陆二维码
	GetMpLoginQrcode(ctx context.Context, appId string) (*object.WechatMpQrcode, error)
}

type loginChImpl struct {
	*Dao
	openClientPool *rpc.Pool
	name           string
}

var lChRepo LoginChannelRepo

// GetLoginChannelRepo return LoginChannelRepo repo
func GetLoginChannelRepo() LoginChannelRepo {
	return lChRepo
}

// InitLoginChannelRepo injects LoginChannelRepo with implementation
func InitLoginChannelRepo(l LoginChannelRepo) {
	lChRepo = l
}

// NewLoginChannelRepo initialize
func NewLoginChannelRepo(openPool *rpc.Pool) *loginChImpl {
	return &loginChImpl{
		Dao:            dao,
		openClientPool: openPool,
		name:           "dao_login_channel",
	}
}

// CreateLoginChannel 新增渠道
func (l *loginChImpl) CreateLoginChannel(ctx context.Context, channel *model.LoginChannel) (int64, error) {
	if channel == nil {
		return 0, nil
	}
	if channel.CreatedAt.IsZero() {
		channel.CreatedAt = util.GetNow()
		channel.UpdatedAt = util.GetNow()
	}
	param := []interface{}{
		channel.AccId,
		channel.Platform,
		channel.AppId,
		channel.OpenId,
		channel.UnionId,
		channel.Nickname,
		channel.Avatar,
		channel.CreatedAt,
		channel.UpdatedAt,
	}
	query := "INSERT INTO login_channel (acc_id, platform, app_id, open_id, union_id, nickname, avatar, created_at, updated_at) " +
		"VALUES (?,?,?,?,?,?,?,?,?)"

	aff, err := l.db.PgExec(ctx, "id", query, param...)
	if err != nil {
		return 0, nil
	}
	lastId, _ := aff.GetLastId()
	return lastId, nil
}

// GetLoginChannelByOpenId 根据 openid 查询渠道
func (l *loginChImpl) GetLoginChannelByOpenId(ctx context.Context, appId, openId string, platform int8) (*model.LoginChannel, error) {
	query := "SELECT * FROM login_channel WHERE app_id=? AND open_id=? AND platform=? AND deleted_at=0"
	ch := &model.LoginChannel{}
	err := l.db.Get(ctx, ch, query, appId, openId, platform)
	if err != nil && errors.Is(err, pgex.ErrEmpty) {
		return nil, nil
	}
	return ch, err
}

// GetMpLoginQrcode 获取登陆二维码
func (l *loginChImpl) GetMpLoginQrcode(ctx context.Context, appId string) (*object.WechatMpQrcode, error) {
	rId := strings.ReplaceAll(uuid.New().String(), "-", "")
	action := &open_pb.ActionInfo{
		SceneStr: rId,
	}
	req := &open_pb.CreateQRCodeTicketRequest{
		AppId:         appId,
		ActionName:    "QR_STR_SCENE",
		ActionInfo:    action,
		ExpireSeconds: 600, // 十分钟后过期
	}
	conn, err := l.openClientPool.Get(ctx)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = conn.Close()
	}()
	client := open_pb.NewOpenServiceClient(conn.ClientConn)
	resp, err := client.CreateQRCodeTicket(ctx, req)
	if err != nil {
		return nil, err
	}
	return &object.WechatMpQrcode{
		Ticket:        resp.Ticket,
		ExpireSeconds: resp.ExpireSeconds,
		Url:           resp.Url,
	}, nil
}
